function [salary, fringe, hins] = budget(yr, grantid, SAL, INST, GRANT, begin_date, end_date)
% computes salary, fringe and health insurance over
% the period given in begin, end. Result is an array.
% ny is the year number in the grant (used to extract fringe rates, etc)
% assumes budget year rolls over on July 1
% if beg, end covers more than one year, the results are
% stored in successive elements of the array.
% the SAL structure:
% SAL.who = person named
% sal.what = position title
% SAL.base = base salary at start of period
% SAL.class = position (may affect calculations)
% SAL.anniv = anniversary date
% SAL.apptstart = start date
% SAL.apptend = end date
% SAL.increment = yearly increment
%
% GRANT structure:
% GRANT.begin : start date of the grant (day, month)
% GRANT.name : information on name of the grant
% GRANT.IDC: IDC rate on the grant (may vary depending on the grant)
%
% the institutional information:
% INST.fringe = fringe benefits rate
% INST.hins = health insurance (monthly rate...)
% 8/Feb/1999 P. Manis
%
salary = [];
fringe=[];
hins = [];
if(nargin<5)
   disp('Requires: SAL, INST, GRANT, begin, end')
   stop
end
d_beg = datenum(begin_date);
d_end = datenum(end_date);
g_beg = datenum(GRANT.begin);
s_anniv = datenum(SAL.anniv);
start = datenum(SAL.apptstart);
year = 365;
g_end = g_beg+year;
effort = SAL.grant(grantid).effort(yr);
c_beg = max(g_beg, d_beg);
c_end = min(d_end);

% move salary anniversary into the range of the current grant period
[s_anniv] = make_in_window(c_beg, s_anniv);
%disp(sprintf('anniv: %s  relative to grant start of %s', datestr(s_anniv), datestr(d_beg)))

% from start of employment (or grant begin) to the anniversary date, and beyond
[sal1p, sal2p] = year_split(c_beg, c_end, s_anniv);
% disp(sprintf('First: %d days, second: %d days, total: %d days', sal1p, sal2p, (sal1p+sal2p)))

% compute the salary in the grant period now
sal1 = sal1p * SAL.base(yr) /year;
sal2 = sal2p * SAL.base(yr) * (SAL.increment + 1)/year;
%disp(sprintf('base: %8.2f  sal1: %d sal2: %d, inc: %7.2f', SAL.base(yr), sal1, sal2, SAL.increment))
salary = (sal1+sal2)*effort; % adjust salary by effort

% compute the fringe
fr_anniv = make_in_window(c_beg, datenum(INST.fringedate));
disp(sprintf('Fringe Anniv: %s  vs %s', datestr(fr_anniv), datestr(c_beg)))
[fr1p, fr2p] = year_split(c_beg, c_end, fr_anniv);
avfringerate = fr1p*INST.fringe(yr)/year + fr2p*INST.fringe(yr+1)/year; % just get the average over the period in question.
fringe = salary*avfringerate; 
hins = effort*INST.hins(SAL.class, yr)*12*(c_end-c_beg)/year; % prorate over period of employment

% print information in order needed for the grant... or to put into a worksheet
if(salary <= 0) % don't print it if there is none...
   return
end

   disp(sprintf('%-25s %-20s %6.0f %10.2f %10.2f %10.2f',...
   SAL.who, SAL.what, SAL.grant(grantid).effort(yr)*100, salary, (fringe+hins), (salary+fringe+hins)))

return

function [d] = daysinyear(date)
% compute days in a year - to account for leap years
% assumes that date is a num format...
%
v = datevec(date);
v(1) = v(1)+1;
nextyear = vecdate(v);
d = nextyear - date + 1;
return

function [d] = addyear(date, nyr)
% add a number of years to the date
% % input is in datenum format...
v = datevec(date); % convert to vector
v(1) = v(1)+nyr; % access year
d = vecdate(v); % convert back to num
return

function [before, after, err] = year_split(begin, bend, split)
% compute the number of days before and after a particular splitting date
% between the two dates at begin and end. Dates are assumed to be in "num" format
% Note that an err ~= 0 returned if begin > end
%		split not in [begin, end] range
%
if(begin > bend)
   err = 1
   return
end
if(split < begin)
   before = 0;
   after = bend - split; % assign it all to after
   return
end
if(split > bend)
   after = 0;
   before = split - begin; % assign it all to before
   err = 1;
   return
end
before = split - begin; % split it between the two
after = bend - split;
return

function [inwin] = make_in_window(beg, s)
% make the date associated with s fall in the year after
% beg; resulting date is in inwin
% inputs are in datenum format...
inwin = s;
if(inwin < beg(1))
   while(inwin < beg) 
      inwin = addyear(inwin, 1);
   end
else
   while(inwin >= beg)
      inwin = addyear(inwin, -1);
   end
   inwin  = addyear(inwin, 1);
end
%disp(sprintf('b: %s  d: %s', datestr(beg),datestr(inwin)))

function [d] = vecdate(v)
% turn vector in date number... only works on dates...
%
d = datenum(v(1), v(2), v(3));
return;

